#!/usr/bin/env python
"""
rhut is short for "Raymond Hettinger Unit Tester"

Adapted to run a test with code coverage from the command line from...
http://code.activestate.com/recipes/572194-lightweight-unittester/?in=user-178123

Thanks to Raymond Hettinger!
"""

def run_test_functions(source=None):
    from sys import stderr
    from types import GeneratorType

    # source can be module, class, None, or a dictionary
    if source is None:
        ns = globals()
    elif isinstance(source, dict):
        ns = dict(source)
    else:
        ns = vars(source)

    tests = [(name, func) for name, func in ns.items() if name.startswith('test_')]
    tests = sorted(tests, reverse=True)

    successes = failures = 0
    while tests:
        name, func = tests.pop()
        try:
            rv = func()
        except Exception, E:
            failures += 1
            print name, '...', repr(E)
        else:
            if isinstance(rv, GeneratorType):
                pairs = []
                for func, arg in rv:
                    gname = 'gen:%s(%r)' % (name, arg)
                    gfunc = lambda func=func, arg=arg: func(arg)
                    pairs.append((gname, gfunc))
                tests.extend(reversed(pairs))
            else:
                successes += 1
                print name, '... Success'

    result = (successes+failures, failures)
    print 'Ran %d tests with %d failures' % result
    return result

if __name__=='__main__':
    import sys, importlib, coverage, os
    path, module = os.path.split(sys.argv[1])
    if path not in sys.path:
        sys.path.append(path)
    cov = coverage.coverage()
    cov.start()
    run_test_functions(importlib.import_module(module))
    cov.stop()
    cov.report(omit=['*rhut.py'])
